package main

import (
	"back_go/Common"
	"back_go/DAO/gorm"
	"back_go/Middleware"
	"back_go/Middleware/Log"
	"back_go/Router"
	"bytes"
	"fmt"
	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"github.com/robfig/cron/v3"
	"go.uber.org/zap"
	"gopkg.in/ini.v1"
	"io"
	"log"
	"net/http"
)

// @title Swagger Example API
// @version 1.0
// @description This is a sample server Petstore server.
// @termsOfService http://swagger.io/terms/

// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host petstore.swagger.io
// @host localhost:8080
func getRequestBody(c *gin.Context) string {
	// 设置最大请求体大小，防止内存溢出攻击
	const maxBodySize = 20 << 20 // 20MB
	if c.Request.ContentLength > int64(maxBodySize) {
		c.JSON(http.StatusRequestEntityTooLarge, gin.H{"error": "request body too large"})
		c.Abort()
		return ""
	}

	bodyBytes, err := io.ReadAll(c.Request.Body)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "failed to read request body"})
		c.Abort()
		return ""
	}

	// 将读取的内容重新设置回请求体
	c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))

	return string(bodyBytes)
}

func main() {

	logger := Log.InitLoggerWithRedisStream()
	defer logger.Sync()

	//gin.SetMode(gin.ReleaseMode)
	//gin.DefaultWriter = ioutil.Discard
	r := gin.Default()

	//初始化minio
	Middleware.InitMinio()
	//初始cache
	Middleware.InitCache()
	//初始化xorm
	gorm.InitGormDB()

	config := cors.DefaultConfig()
	//config.AllowOrigins = []string{"http://localhost:9526"}
	config.AllowOrigins = []string{"http://localhost", "http://localhost:8080", "http://192.168.3.63:8080", "http://192.168.3.63:80", "http://localhost:9526"}
	config.AllowMethods = []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"}
	config.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "Authorization"}
	config.AllowCredentials = true

	r.Use(cors.New(config))
	//鉴权中间件
	//r.Use(Middleware.AuthMiddleware(Middleware.RedisClient, "/adminLogin", "/test"))

	r.Use(func(c *gin.Context) {
		path := c.Request.URL.Path
		if path != "/admin/upload" && path != "/admin/file/upload/element" {

			_, username, _ := Common.CodeToken(c.GetHeader("Authorization"))
			logger.Info("request started",
				zap.String("method", c.Request.Method),
				zap.String("path", c.Request.URL.Path),
				zap.String("query", c.Request.URL.RawQuery),
				zap.String("body", getRequestBody(c)),
				zap.String("ip", c.RemoteIP()),
				zap.String("username", username),
			)
		} else {
			_, username, _ := Common.CodeToken(c.GetHeader("Authorization"))
			logger.Info("request started",
				zap.String("method", c.Request.Method),
				zap.String("path", c.Request.URL.Path),
				zap.String("query", c.Request.URL.RawQuery),
				zap.String("ip", c.RemoteIP()),
				zap.String("username", username),
			)
		}
		c.Next()

	})

	cronJob := cron.New()
	_, err := cronJob.AddFunc("@every 10s", func() {
		redisConsumer := Log.GetRedisConsumer()
		redisConsumer.ConsumeMessagesFromRedisAndStoreInMySQL()
	})
	if err != nil {
		fmt.Println("添加定时任务失败：", err)
		return
	}

	// 启动 cron 任务
	cronJob.Start()

	Router.InitRouter(r)
	routes := r.Routes()
	routeCount := len(routes)
	fmt.Println("Total routes:", routeCount)

	//获取监听接口和地址
	cfg, err := ini.Load("./Config/config.ini")
	if err != nil {
		log.Fatalf("Failed to load config: %v", err)
	}
	log.Println(cfg.Section("server_config").Key("host").String() + ":" + cfg.Section("server_config").Key("port").String())
	if err := r.Run(cfg.Section("server_config").Key("host").String() + ":" + cfg.Section("server_config").Key("port").String()); err != nil {
		log.Fatalf("Failed to start server: %v", err)
	}
}
